﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using CapaDeDominio;
using System.Data.Entity.Validation;

namespace CapaDeDatos.EF
{
    public class SalaDAO : ISalaDAO
    {
        #region IBaseDAO<Sala,int> Members

        /// <summary>
        /// Crear Sala
        /// </summary>
        /// <param name="SalaACrear">Dominio Sala</param>
        /// <returns>Dominio Sala</returns>
        public Sala Crear(Sala SalaACrear)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                    int? codigo = db.Salas.Select(l => (int?)l.Codigo).Max();
                    SalaACrear.Codigo = (codigo ?? 0) + 1;
                    db.Locales.Attach(SalaACrear.Local);
                    db.Salas.Add(SalaACrear);
                    db.SaveChanges();
            }
            return Obtener(SalaACrear.Codigo);
        }

        /// <summary>
        /// Obtener Sala
        /// </summary>
        /// <param name="Codigo">Codigo de la Sala</param>
        /// <returns></returns>
        public Sala Obtener(int Codigo)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                var sala = from l in db.Salas
                           .Include("Local")
                           .Include("Instrumentos")
                           .Include("Servicios")
                           where l.Codigo == Codigo
                           select l;
                return sala.SingleOrDefault();
            }
        }

        public void Eliminar(Sala itemEliminar)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                Sala sala = db.Salas.Single(i => i.Codigo == itemEliminar.Codigo);
                db.Salas.Remove(sala);
                db.SaveChanges();
            }
        }

        /// <summary>
        /// Listar Sala
        /// </summary>
        /// <returns>Colleccion de Sala</returns>
        public ICollection<Sala> ListarTodos()
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                var resultado = from l in db.Salas
                                .Include("Local")
                                .Include("Instrumentos")
                                .Include("Servicios")
                                select l;
                return resultado.ToList();
            }
        }

        #endregion

        #region ISalaDAO Members

        public int ListarXCoincidencia(string nombre, Local local)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                var resultado = from l in db.Salas
                                .Include("Local")
                                .Include("Instrumentos")
                                .Include("Servicios")
                                where (l.Nombre == nombre)
                                where (l.Local.Codigo == local.Codigo)                                
                                select l.Codigo;

                return resultado.Count();
            }
        }

        /// <summary>
        /// Listar por filtros (hay que verificar los parametros y recorrer los servicios: buscar como hacerlo con lambda)
        /// </summary>
        /// <param name="nombre"></param>
        /// <param name="local"></param>
        /// <param name="instrumento"></param>
        /// <param name="Capacidad"></param>
        /// <returns></returns>
        public ICollection<Sala> ListarXFiltros(string nombre, Local local, int Guitarras, bool teclado, int capacidad, Servicio servicioGrab)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                var reservas = from c in db.Reservas
                               .Include("Cliente")
                               .Include("Sala")
                               .Include("InstrumentosAdicionales")
                               .Include("ServiciosAdicionales")
                               select c.Sala.Codigo;

                var resultado = from l in db.Salas
                                select l;

                if (nombre != "")
                    resultado = from c in resultado
                                where (c.Nombre == nombre)
                                select c;

                if(local!=null)
                    resultado = from c in resultado where(c.Local.Codigo == local.Codigo)
                                select c;

                //siendo tipo 1 guitarra
                if (Guitarras != -1)
                {                    
                    foreach(Sala s in resultado.ToList())
                    {
                        if(s.Instrumentos.GroupBy(a=>a.Tipo.GetHashCode()==1).Count() < Guitarras)
                            resultado.ToList().Remove(s);                        
                    }
                }

                //siendo tipo 2 teclado
                if (teclado)
                {
                    foreach (Sala s in resultado.ToList())
                    {
                        if (s.Instrumentos.GroupBy(a => a.Tipo.GetHashCode() == 2).Count() < 1)
                            resultado.ToList().Remove(s);
                    }
                }

                if (capacidad != -1)
                    resultado = from c in resultado
                                where (c.Capacidad == capacidad)
                                select c;

                if (servicioGrab != null)
                {
                    Sala salaItem = null;
                    for (int j = 0; j < resultado.ToList().Count; j++) 
                    {
                        salaItem=null;
                        for(int i=0; i< resultado.ToList().ElementAt(j).Servicios.Count; i++){
                            if (resultado.ToList().ElementAt(j).Servicios.ElementAt(i).Codigo == servicioGrab.Codigo) 
                            {                             
                                salaItem=resultado.ToList().ElementAt(j);
                                break;
                            }
                        }

                        if(salaItem!=null)
                            resultado.ToList().Remove(salaItem);
                    }

                    /*resultado = from c in resultado
                                where c.Servicios.Contains(servicioGrab)
                                select c;*/
                }
                /*foreach (Sala s in resultado.ToList())
                {
                    if (((Reserva)reservas).Codigo==s.Codigo)
                        resultado.ToList().Remove(s);
                }*/

                resultado = from c in resultado
                            select c;

                return resultado.ToList();
            }
        }

        #endregion

        #region ISalaDAO Members


        public void AsignarInstrumentos(int codigo, ICollection<Instrumento> instrumentos)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                Sala salaAModificar = db.Salas.Single(l => l.Codigo == codigo);
                salaAModificar.Instrumentos = new List<Instrumento>();  
                foreach (Instrumento instrumento in instrumentos)
                    salaAModificar.Instrumentos.Add(db.Instrumentos.Single(l => l.Codigo == instrumento.Codigo));
                db.SaveChanges();
            }
        }

        public void AsignarServicios(int codigo, ICollection<Servicio> servicios)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                Sala salaAModificar = db.Salas.Single(l => l.Codigo == codigo);
                salaAModificar.Servicios = new List<Servicio>();
                foreach (Servicio servicio in servicios)
                    salaAModificar.Servicios.Add(db.Servicios.Single(l => l.Codigo == servicio.Codigo));
                db.SaveChanges();
            }
        }

        public void ActualizarCosto(int codigo, decimal alquiler)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                    Sala salaAModificar = db.Salas.Single(l => l.Codigo == codigo);
                    salaAModificar.alquiler = alquiler;
                    db.SaveChanges();
            }
        }

        public ICollection<Sala> ListarXBusqueda(int? codigo, string nombre, string caracteristicas, int? capacidad, Local local, string comentarios)
        {
            using (EFContext db = new EFContext(ConexionUtil.ObtenerCadena()))
            {
                var busqueda = from s in db.Salas
                                   .Include("Local")
                                   .Include("Instrumentos")
                                   .Include("Servicios")
                               select s;
                if (codigo != null)
                    busqueda = busqueda.Where(s => s.Codigo == codigo);
                if (nombre != null)
                    busqueda = busqueda.Where(s => s.Nombre.Contains(nombre));
                if (caracteristicas != null)
                    busqueda = busqueda.Where(s => s.Caracteristicas.Contains(caracteristicas));
                if (capacidad != null)
                    busqueda = busqueda.Where(s => s.Capacidad == capacidad);
                if (local != null)
                {
                    Sala salaItem = null;
                    for (int j = 0; j < busqueda.ToList().Count; j++)
                    {
                        salaItem = null;
                        if (busqueda.ToList().ElementAt(j).Local.Codigo == local.Codigo)
                        {
                            salaItem = busqueda.ToList().ElementAt(j);
                            busqueda.ToList().Remove(salaItem);
                        }
                    }

                    //busqueda = busqueda.Where(s => s.Local == local);
                }
                
                if (comentarios != null)
                    busqueda = busqueda.Where(s => s.Comentarios.Contains(comentarios));
                return busqueda.ToList();
            }
        }

        #endregion
    }
}